#ifndef BASIC_TYPE_H_
#define BASIC_TYPE_H_

#include <Eigen/Core>
#include <iostream>
#include <memory>
#include <opencv2/opencv.hpp>
#include <string>

#include "basic_settings.h"
#include "circular_queue.h"
#include "fixed_array.h"

namespace autodrive {
namespace perception {
/// @brief rect struct
struct Rect {
  /// @brief x-coordinate of upper left corner (lowest memory address).
  std::int32_t x;
  /// @brief y-coordinate of upper left corner (lowest memory address).
  std::int32_t y;
  /// @brief  Rectangle height.
  std::int32_t height;
  /// @brief Rectangle width.
  std::int32_t width;
};

struct Size {
  /// @brief height.
  std::int32_t height;
  /// @brief width.
  std::int32_t width;
};

struct Vector3f {
  /// @brief x/roll
  float x;
  /// @brief y/pitch
  float y;
  /// @brief z/yaw
  float z;
};

struct Vector2f {
  /// @brief x
  float x;
  /// @brief y
  float y;
};

struct GridPosition {
  /// @brief x
  std::uint32_t x;
  /// @brief y
  std::uint32_t y;
  /// @brief pos
  std::uint32_t pos;
  /// @brief reg
  std::uint32_t reg;
};

/// @brief sparse data
template <typename P, typename F>
struct SparseData {
  /// @brief position in feature map
  P position;
  /// @brief feature
  F feature;
};

// Point XYZIT
struct PointXYZIT {
  ///@brief X
  float x;
  ///@brief Y
  float y;
  ///@brief Z
  float z;
  ///@brief Intensity
  float intensity;
  ///@brief Time stamp
  double timestamp;
  ///@brief Ring number
  std::uint16_t ring;
};

template <typename T>
struct PointCloudFeature {
  /// @brief X
  T x;
  /// @brief Y
  T y;
  /// @brief Z
  T z;
  /// @brief Intensity
  T intensity;
  /// @brief X another feature
  T x_b;
  /// @brief Y another feature
  T y_b;
};

template <typename F>
using PointCloudSparseData = SparseData<std::uint32_t, PointCloudFeature<F>>;

struct MatrixData {
  ///@brief name
  std::string name;
  ///@brief timestamp
  std::uint64_t timestamp;
  ///@brief calibration matrix
  Eigen::MatrixXd mat;
  ///@brief is valid
  bool is_valid;
};

///@brief max rtk queue size
constexpr std::uint32_t kMaxRTKQueueSize{512U};

using RTKDataBuffer = CircularQueue<MatrixData, kMaxRTKQueueSize>;

using RTKDataBufferPtr = std::shared_ptr<RTKDataBuffer>;

/// @brief max calib data number
static constexpr std::uint32_t kMaxCalibDataNum{64};
///@brief max matrix data size
static constexpr std::uint32_t kMaxCalibDataSize{16U};

/// @brief calib data
struct CalibData {
  /// @brief name
  std::string name;
  /// @brief data
  fixed_array<double, kMaxCalibDataSize> data;
  /// @brief is valid
  bool is_valid;
};

/// @brief calib data set
struct CalibDataSet {
  /// @brief id
  std::string id;
  /// @brief data set
  fixed_array<CalibData, kMaxCalibDataNum> data_set;
  /// @brief  update flag
  std::int32_t update_flag;
};

/// calib data array pointer
using CalibDataSetPtr = std::shared_ptr<CalibDataSet>;

///@brief max camera number
static constexpr std::uint32_t kMaxCameraNum{11U};

template <typename T>
struct ImageSource {
  ///@brief timestamp
  std::uint64_t timestamp;
  /// @brief source image
  fixed_array<cv::Mat, kMaxCameraNum> images;
  /// @brief normalize with nchw
  std::vector<T> norm;
};

template <typename T>
using ImageSourcePtr = ImageSource<T> *;

///@brief max point cloud number
static constexpr std::uint32_t kMaxPointNum{400000U};

struct PointCloudSource {
  ///@brief timestamp
  std::uint64_t timestamp;
  /// @brief points
  fixed_array<PointXYZIT, kMaxPointNum> points;
};

using PointCloudSourcePtr = PointCloudSource *;

}  // namespace perception
}  // namespace autodrive

#endif  // !BASIC_TYPE_H_
